From 6b75d294b540eb07d439c07348f3cc3e8b83966d Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Mon, 8 Nov 2004 18:37:51 +0000 Subject: [PATCH] bitkeeper revision 1.1159.170.1 (418fbcfftbJRf270n_KReJDuXIouGg) Rejig the layout of saved activations on Xen's stack. Touches a bunch of stuff but things are generally a bit cleaner now. Should be easier to integrate vm86 support, and I'm now ready to do bigger changes to the Xen->guest exit code. --- .rootkeys | 1 + xen/arch/x86/traps.c | 23 +- xen/arch/x86/x86_32/entry.S | 332 ++++++++----------------- xen/include/asm-x86/irq.h | 31 +-- xen/include/asm-x86/x86_32/asm_defns.h | 122 +++++++++ xen/include/asm-x86/x86_32/current.h | 10 +- xen/include/asm-x86/x86_32/regs.h | 80 +++--- xen/include/public/arch-x86_32.h | 8 +- xen/include/public/dom0_ops.h | 2 +- xen/include/xen/sched.h | 11 +- 10 files changed, 305 insertions(+), 315 deletions(-) create mode 100644 xen/include/asm-x86/x86_32/asm_defns.h diff --git a/.rootkeys b/.rootkeys index 0b9dde39da..2a93a73cac 100644 --- a/.rootkeys +++ b/.rootkeys @@ -731,6 +731,7 @@ 3ddb79c3ezddh34MdelJpa5tNR00Dw xen/include/asm-x86/system.h 3ddb79c4HugMq7IYGxcQKFBpKwKhzA xen/include/asm-x86/types.h 40cf1596saFaHD5DC5zvrSn7CDCWGQ xen/include/asm-x86/uaccess.h +418fbcfe_WliJPToeVM-9VStvym-hw xen/include/asm-x86/x86_32/asm_defns.h 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h 3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h 3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 8f6cb3c694..3f7793c36e 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -166,14 +166,25 @@ void show_stack(unsigned long *esp) void show_registers(struct xen_regs *regs) { unsigned long esp; - unsigned short ss; + unsigned short ss, ds, es, fs, gs; - esp = (unsigned long)(®s->esp); - ss = __HYPERVISOR_DS; if ( regs->xcs & 3 ) { esp = regs->esp; ss = regs->xss & 0xffff; + ds = regs->xds & 0xffff; + es = regs->xes & 0xffff; + fs = regs->xfs & 0xffff; + gs = regs->xgs & 0xffff; + } + else + { + esp = (unsigned long)(®s->esp); + ss = __HYPERVISOR_DS; + ds = __HYPERVISOR_DS; + es = __HYPERVISOR_DS; + fs = __HYPERVISOR_DS; + gs = __HYPERVISOR_DS; } printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n", @@ -183,8 +194,7 @@ void show_registers(struct xen_regs *regs) printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", regs->esi, regs->edi, regs->ebp, esp); printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", - regs->xds & 0xffff, regs->xes & 0xffff, - regs->xfs & 0xffff, regs->xgs & 0xffff, ss); + ds, es, fs, gs, ss); show_stack(®s->esp); } @@ -230,7 +240,6 @@ static inline void do_trap(int trapnr, char *str, { DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup); regs->eip = fixup; - regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS; return; } @@ -394,7 +403,6 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) if ( !d->mm.shadow_mode ) DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup); regs->eip = fixup; - regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS; return; } @@ -509,7 +517,6 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) { DPRINTK("GPF (%04lx): %08lx -> %08lx\n", error_code, regs->eip, fixup); regs->eip = fixup; - regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS; return; } diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 9a792d19f9..474b399b59 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -59,76 +59,9 @@ #include #include #include +#include #include -EBX = 0x00 -ECX = 0x04 -EDX = 0x08 -ESI = 0x0C -EDI = 0x10 -EBP = 0x14 -EAX = 0x18 -DS = 0x1C -ES = 0x20 -FS = 0x24 -GS = 0x28 -ORIG_EAX = 0x2C -EIP = 0x30 -CS = 0x34 -EFLAGS = 0x38 -OLDESP = 0x3C -OLDSS = 0x40 - -/* Offsets in domain structure */ -PROCESSOR = 0 -SHARED_INFO = 4 -EVENT_SEL = 8 -EVENT_ADDR = 12 -FAILSAFE_BUFFER = 16 -FAILSAFE_SEL = 32 -FAILSAFE_ADDR = 36 - -/* Offsets in shared_info_t */ -#define UPCALL_PENDING /* 0 */ -#define UPCALL_MASK 1 - -/* Offsets in guest_trap_bounce */ -GTB_ERROR_CODE = 0 -GTB_CR2 = 4 -GTB_FLAGS = 8 -GTB_CS = 10 -GTB_EIP = 12 -GTBF_TRAP = 1 -GTBF_TRAP_NOCODE = 2 -GTBF_TRAP_CR2 = 4 - -CF_MASK = 0x00000001 -IF_MASK = 0x00000200 -NT_MASK = 0x00004000 - -#define SAVE_ALL_NOSEGREGS \ - cld; \ - pushl %gs; \ - pushl %fs; \ - pushl %es; \ - pushl %ds; \ - pushl %eax; \ - pushl %ebp; \ - pushl %edi; \ - pushl %esi; \ - pushl %edx; \ - pushl %ecx; \ - pushl %ebx; \ - -#define SAVE_ALL \ - SAVE_ALL_NOSEGREGS \ - movl $(__HYPERVISOR_DS),%edx; \ - movl %edx,%ds; \ - movl %edx,%es; \ - movl %edx,%fs; \ - movl %edx,%gs; \ - sti; - #define GET_CURRENT(reg) \ movl $4096-4, reg; \ orl %esp, reg; \ @@ -226,17 +159,10 @@ multicall_fixup1: ALIGN restore_all_guest: - # First, may need to restore %ds if clobbered by create_bounce_frame - pushl %ss - popl %ds - # Second, create a failsafe copy of DS,ES,FS,GS in case any are bad - leal DS(%esp),%esi - leal FAILSAFE_BUFFER(%ebx),%edi - movsl - movsl - movsl - movsl - # Finally, restore guest registers -- faults will cause failsafe +1: movl XREGS_ds(%esp),%ds +2: movl XREGS_es(%esp),%es +3: movl XREGS_fs(%esp),%fs +4: movl XREGS_gs(%esp),%gs popl %ebx popl %ecx popl %edx @@ -244,62 +170,50 @@ restore_all_guest: popl %edi popl %ebp popl %eax -1: popl %ds -2: popl %es -3: popl %fs -4: popl %gs addl $4,%esp 5: iret .section .fixup,"ax" -10: subl $4,%esp - pushl %gs -9: pushl %fs -8: pushl %es -7: pushl %ds -6: pushl %eax +6: subl $4,%esp + pushl %eax pushl %ebp pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx - pushl %ss - popl %ds - pushl %ss - popl %es - jmp failsafe_callback +7: SET_XEN_SEGMENTS + jmp failsafe_callback .previous .section __ex_table,"a" .align 4 - .long 1b,6b + .long 1b,7b .long 2b,7b - .long 3b,8b - .long 4b,9b - .long 5b,10b + .long 3b,7b + .long 4b,7b + .long 5b,6b .previous /* No special register assumptions */ failsafe_callback: GET_CURRENT(%ebx) - movl PROCESSOR(%ebx),%eax + movl DOMAIN_processor(%ebx),%eax shl $4,%eax lea guest_trap_bounce(%eax),%edx - movl FAILSAFE_ADDR(%ebx),%eax - movl %eax,GTB_EIP(%edx) - movl FAILSAFE_SEL(%ebx),%eax - movw %ax,GTB_CS(%edx) + movl DOMAIN_failsafe_addr(%ebx),%eax + movl %eax,GTB_eip(%edx) + movl DOMAIN_failsafe_sel(%ebx),%eax + movw %ax,GTB_cs(%edx) call create_bounce_frame subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame - leal FAILSAFE_BUFFER(%ebx),%ebp - movl 0(%ebp),%eax # DS -FAULT1: movl %eax,(%esi) - movl 4(%ebp),%eax # ES -FAULT2: movl %eax,4(%esi) - movl 8(%ebp),%eax # FS -FAULT3: movl %eax,8(%esi) - movl 12(%ebp),%eax # GS -FAULT4: movl %eax,12(%esi) - movl %esi,OLDESP(%esp) + movl XREGS_ds(%esp),%eax +FAULT1: movl %eax,%gs:(%esi) + movl XREGS_es(%esp),%eax +FAULT2: movl %eax,%gs:4(%esi) + movl XREGS_fs(%esp),%eax +FAULT3: movl %eax,%gs:8(%esi) + movl XREGS_gs(%esp),%eax +FAULT4: movl %eax,%gs:12(%esi) + movl %esi,XREGS_esp(%esp) popl %ebx popl %ecx popl %edx @@ -307,15 +221,10 @@ FAULT4: movl %eax,12(%esi) popl %edi popl %ebp popl %eax - addl $20,%esp # skip DS/ES/FS/GS/ORIG_EAX + addl $4,%esp FAULT5: iret - ALIGN -# Simple restore -- we should never fault as we we will only interrupt ring 0 -# when sane values have been placed in all registers. The only exception is -# NMI, which may interrupt before good values have been placed in DS-GS. -# The NMI return code deals with this problem itself. restore_all_xen: popl %ebx popl %ecx @@ -324,10 +233,6 @@ restore_all_xen: popl %edi popl %ebp popl %eax - popl %ds - popl %es - popl %fs - popl %gs addl $4,%esp iret @@ -335,37 +240,38 @@ restore_all_xen: ENTRY(hypercall) pushl %eax # save orig_eax SAVE_ALL - GET_CURRENT(%ebx) + sti + GET_CURRENT(%ebx) andl $(NR_hypercalls-1),%eax call *SYMBOL_NAME(hypercall_table)(,%eax,4) ret_from_hypercall: - movl %eax,EAX(%esp) # save the return value + movl %eax,XREGS_eax(%esp) # save the return value test_all_events: xorl %ecx,%ecx notl %ecx cli # tests must not race interrupts /*test_softirqs:*/ - movl PROCESSOR(%ebx),%eax + movl DOMAIN_processor(%ebx),%eax shl $6,%eax # sizeof(irq_cpustat) == 64 test %ecx,SYMBOL_NAME(irq_stat)(%eax,1) jnz process_softirqs /*test_guest_events:*/ - movl SHARED_INFO(%ebx),%eax - testb $0xFF,UPCALL_MASK(%eax) + movl DOMAIN_shared_info(%ebx),%eax + testb $0xFF,SHINFO_upcall_mask(%eax) jnz restore_all_guest - testb $0xFF,UPCALL_PENDING(%eax) + testb $0xFF,SHINFO_upcall_pending(%eax) jz restore_all_guest - movb $1,UPCALL_MASK(%eax) # Upcalls are masked during delivery + movb $1,SHINFO_upcall_mask(%eax) # Upcalls are masked during delivery /*process_guest_events:*/ - movl PROCESSOR(%ebx),%edx - shl $4,%edx # sizeof(guest_trap_bounce) == 16 + movl DOMAIN_processor(%ebx),%edx + shl $4,%edx # sizeof(guest_trap_bounce) == 16 lea guest_trap_bounce(%edx),%edx - movl EVENT_ADDR(%ebx),%eax - movl %eax,GTB_EIP(%edx) - movl EVENT_SEL(%ebx),%eax - movw %ax,GTB_CS(%edx) + movl DOMAIN_event_addr(%ebx),%eax + movl %eax,GTB_eip(%edx) + movl DOMAIN_event_sel(%ebx),%eax + movw %ax,GTB_cs(%edx) call create_bounce_frame jmp restore_all_guest @@ -375,16 +281,16 @@ process_softirqs: call SYMBOL_NAME(do_softirq) jmp test_all_events -/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */ -/* {EIP, CS, EFLAGS, [ESP, SS]} */ -/* %edx == guest_trap_bounce, %ebx == task_struct */ -/* %eax,%ecx are clobbered. %ds:%esi contain new OLDSS/OLDESP. */ +/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */ +/* {EIP, CS, EFLAGS, [ESP, SS]} */ +/* %edx == guest_trap_bounce, %ebx == task_struct */ +/* %eax,%ecx are clobbered. %gs:%esi contain new XREGS_ss/XREGS_esp. */ create_bounce_frame: - mov CS+4(%esp),%cl + mov XREGS_cs+4(%esp),%cl test $2,%cl jz 1f /* jump if returning to an existing ring-1 activation */ /* obtain ss/esp from TSS -- no current ring-1 activations */ - movl PROCESSOR(%ebx),%eax + movl DOMAIN_processor(%ebx),%eax /* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */ movl %eax, %ecx shll $7, %ecx @@ -392,38 +298,37 @@ create_bounce_frame: addl %ecx,%eax addl $init_tss + 12,%eax movl (%eax),%esi /* tss->esp1 */ -FAULT6: movl 4(%eax),%ds /* tss->ss1 */ +FAULT6: movl 4(%eax),%gs /* tss->ss1 */ /* base of stack frame must contain ss/esp (inter-priv iret) */ subl $8,%esi - movl OLDESP+4(%esp),%eax -FAULT7: movl %eax,(%esi) - movl OLDSS+4(%esp),%eax -FAULT8: movl %eax,4(%esi) + movl XREGS_esp+4(%esp),%eax +FAULT7: movl %eax,%gs:(%esi) + movl XREGS_ss+4(%esp),%eax +FAULT8: movl %eax,%gs:4(%esi) jmp 2f 1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */ - movl OLDESP+4(%esp),%esi -FAULT9: movl OLDSS+4(%esp),%ds + movl XREGS_esp+4(%esp),%esi +FAULT9: movl XREGS_ss+4(%esp),%gs 2: /* Construct a stack frame: EFLAGS, CS/EIP */ subl $12,%esi - movl EIP+4(%esp),%eax -FAULT10:movl %eax,(%esi) - movl CS+4(%esp),%eax -FAULT11:movl %eax,4(%esi) - movl EFLAGS+4(%esp),%eax -FAULT12:movl %eax,8(%esi) + movl XREGS_eip+4(%esp),%eax +FAULT10:movl %eax,%gs:(%esi) + movl XREGS_cs+4(%esp),%eax +FAULT11:movl %eax,%gs:4(%esi) + movl XREGS_eflags+4(%esp),%eax +FAULT12:movl %eax,%gs:8(%esi) /* Rewrite our stack frame and return to ring 1. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ andl $0xfffcbeff,%eax - movl %eax,EFLAGS+4(%esp) - movl %ds,OLDSS+4(%esp) - movl %esi,OLDESP+4(%esp) - movzwl %es:GTB_CS(%edx),%eax - movl %eax,CS+4(%esp) - movl %es:GTB_EIP(%edx),%eax - movl %eax,EIP+4(%esp) + movl %eax,XREGS_eflags+4(%esp) + movl %gs,XREGS_ss+4(%esp) + movl %esi,XREGS_esp+4(%esp) + movzwl GTB_cs(%edx),%eax + movl %eax,XREGS_cs+4(%esp) + movl GTB_eip(%edx),%eax + movl %eax,XREGS_eip+4(%esp) ret - - + .section __ex_table,"a" .align 4 .long FAULT1, crash_domain_fixup3 # Fault writing to ring-1 stack @@ -447,44 +352,41 @@ FAULT12:movl %eax,8(%esi) crash_domain_fixup1: subl $4,%esp SAVE_ALL + sti jmp domain_crash crash_domain_fixup2: addl $4,%esp crash_domain_fixup3: - pushl %ss - popl %ds jmp domain_crash .previous ALIGN process_guest_exception_and_events: - movl PROCESSOR(%ebx),%eax + movl DOMAIN_processor(%ebx),%eax shl $4,%eax lea guest_trap_bounce(%eax),%edx - testb $~0,GTB_FLAGS(%edx) + testb $~0,GTB_flags(%edx) jz test_all_events call create_bounce_frame # just the basic frame - mov %es:GTB_FLAGS(%edx),%cl + mov GTB_flags(%edx),%cl test $GTBF_TRAP_NOCODE,%cl jnz 2f subl $4,%esi # push error_code onto guest frame - movl %es:GTB_ERROR_CODE(%edx),%eax -FAULT13:movl %eax,(%esi) + movl GTB_error_code(%edx),%eax +FAULT13:movl %eax,%gs:(%esi) test $GTBF_TRAP_CR2,%cl jz 1f subl $4,%esi # push %cr2 onto guest frame - movl %es:GTB_CR2(%edx),%eax -FAULT14:movl %eax,(%esi) -1: movl %esi,OLDESP(%esp) -2: push %es # unclobber %ds - pop %ds - movb $0,GTB_FLAGS(%edx) + movl GTB_cr2(%edx),%eax +FAULT14:movl %eax,%gs:(%esi) +1: movl %esi,XREGS_esp(%esp) +2: movb $0,GTB_flags(%edx) jmp test_all_events ALIGN ENTRY(ret_from_intr) GET_CURRENT(%ebx) - movb CS(%esp),%al + movb XREGS_cs(%esp),%al testb $3,%al # return to non-supervisor? jne test_all_events jmp restore_all_xen @@ -494,36 +396,31 @@ ENTRY(divide_error) pushl $ SYMBOL_NAME(do_divide_error) ALIGN error_code: - pushl %fs - pushl %es - pushl %ds - pushl %eax - xorl %eax,%eax - pushl %ebp + cld + pushl %ebp pushl %edi pushl %esi pushl %edx - decl %eax # eax = -1 pushl %ecx pushl %ebx - cld - movl %gs,%ecx - movl ORIG_EAX(%esp), %esi # get the error code - movl GS(%esp), %edi # get the function address - movl %eax, ORIG_EAX(%esp) - movl %ecx, GS(%esp) - movl $(__HYPERVISOR_DS),%edx - movl %edx,%ds - movl %edx,%es - movl %edx,%fs - movl %edx,%gs + movb XREGS_cs(%esp),%bl + testb $3,%bl + je 1f + movl %ds,XREGS_ds(%esp) + movl %es,XREGS_es(%esp) + movl %fs,XREGS_fs(%esp) + movl %gs,XREGS_gs(%esp) +1: SET_XEN_SEGMENTS + movl XREGS_orig_eax(%esp),%esi # get the error code + movl XREGS_eax(%esp),%edi # get the function address + movl %eax,XREGS_eax(%esp) movl %esp,%edx pushl %esi # push the error code pushl %edx # push the xen_regs pointer GET_CURRENT(%ebx) - call *%edi + call *%edi addl $8,%esp - movb CS(%esp),%al + movb XREGS_cs(%esp),%al testb $3,%al je restore_all_xen jmp process_guest_exception_and_events @@ -628,21 +525,21 @@ ENTRY(nmi) # In all other cases we bail without touching DS-GS, as we have # interrupted an enclosing Xen activation in tricky prologue or # epilogue code. - movb CS(%esp),%al + movb XREGS_cs(%esp),%al testb $3,%al jne do_watchdog_tick - movl DS(%esp),%eax + movl XREGS_ds(%esp),%eax cmpw $(__HYPERVISOR_DS),%ax - jne nmi_badseg - movl ES(%esp),%eax + jne restore_all_xen + movl XREGS_es(%esp),%eax cmpw $(__HYPERVISOR_DS),%ax - jne nmi_badseg - movl FS(%esp),%eax + jne restore_all_xen + movl XREGS_fs(%esp),%eax cmpw $(__HYPERVISOR_DS),%ax - jne nmi_badseg - movl GS(%esp),%eax + jne restore_all_xen + movl XREGS_gs(%esp),%eax cmpw $(__HYPERVISOR_DS),%ax - jne nmi_badseg + jne restore_all_xen do_watchdog_tick: movl $(__HYPERVISOR_DS),%edx @@ -653,34 +550,23 @@ do_watchdog_tick: pushl %edx # regs call SYMBOL_NAME(do_nmi) addl $8,%esp - movb CS(%esp),%al + movb XREGS_cs(%esp),%al testb $3,%al je restore_all_xen GET_CURRENT(%ebx) jmp restore_all_guest -nmi_badseg: - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popl %eax - addl $20,%esp - iret - nmi_parity_err: # Clear and disable the parity-error line andb $0xf,%al orb $0x4,%al outb %al,$0x61 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore - je nmi_badseg + je restore_all_xen bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason) bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat) cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0 - je nmi_badseg + je restore_all_xen movl $(__HYPERVISOR_DS),%edx # nmi=fatal movl %edx,%ds movl %edx,%es @@ -696,11 +582,11 @@ nmi_io_err: orb $0x8,%al outb %al,$0x61 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore - je nmi_badseg + je restore_all_xen bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason) bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat) cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0 - je nmi_badseg + je restore_all_xen movl $(__HYPERVISOR_DS),%edx # nmi=fatal movl %edx,%ds movl %edx,%es diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 83c4c8f614..3b71f7f0a0 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -5,6 +5,7 @@ #include #include +#include extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); @@ -83,36 +84,6 @@ extern char _stext, _etext; #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) -#define __STR(x) #x -#define STR(x) __STR(x) - -#if defined(__i386__) - -#define SAVE_ALL \ - "cld\n\t" \ - "pushl %gs\n\t" \ - "pushl %fs\n\t" \ - "pushl %es\n\t" \ - "pushl %ds\n\t" \ - "pushl %eax\n\t" \ - "pushl %ebp\n\t" \ - "pushl %edi\n\t" \ - "pushl %esi\n\t" \ - "pushl %edx\n\t" \ - "pushl %ecx\n\t" \ - "pushl %ebx\n\t" \ - "movl $" STR(__HYPERVISOR_DS) ",%edx\n\t" \ - "movl %edx,%ds\n\t" \ - "movl %edx,%es\n\t" \ - "movl %edx,%fs\n\t" \ - "movl %edx,%gs\n\t" - -#else - -#define SAVE_ALL - -#endif - #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v) #define XBUILD_SMP_INTERRUPT(x,v)\ asmlinkage void x(void); \ diff --git a/xen/include/asm-x86/x86_32/asm_defns.h b/xen/include/asm-x86/x86_32/asm_defns.h new file mode 100644 index 0000000000..0f022d38a2 --- /dev/null +++ b/xen/include/asm-x86/x86_32/asm_defns.h @@ -0,0 +1,122 @@ +#ifndef __ASM_DEFNS_H__ +#define __ASM_DEFNS_H__ + +/* Offsets in 'struct xen_regs' --- AUTO-GENERATE ME! */ +#define XREGS_ebx 0x00 +#define XREGS_ecx 0x04 +#define XREGS_edx 0x08 +#define XREGS_esi 0x0C +#define XREGS_edi 0x10 +#define XREGS_ebp 0x14 +#define XREGS_eax 0x18 +#define XREGS_orig_eax 0x1C +#define XREGS_eip 0x20 +#define XREGS_cs 0x24 +#define XREGS_eflags 0x28 +#define XREGS_esp 0x2C +#define XREGS_ss 0x30 +#define XREGS_es 0x34 +#define XREGS_ds 0x38 +#define XREGS_fs 0x3C +#define XREGS_gs 0x40 + +/* Offsets in 'struct domain' --- AUTO-GENERATE ME! */ +#define DOMAIN_processor 0 +#define DOMAIN_shared_info 4 +#define DOMAIN_event_sel 8 +#define DOMAIN_event_addr 12 +#define DOMAIN_failsafe_sel 16 +#define DOMAIN_failsafe_addr 20 + +/* Offsets in shared_info_t --- AUTO-GENERATE ME! */ +#define SHINFO_upcall_pending /* 0 */ +#define SHINFO_upcall_mask 1 + +/* Offsets in 'struct guest_trap_bounce' --- AUTO-GENERATE ME! */ +#define GTB_error_code 0 +#define GTB_cr2 4 +#define GTB_flags 8 +#define GTB_cs 10 +#define GTB_eip 12 +#define GTBF_TRAP 1 +#define GTBF_TRAP_NOCODE 2 +#define GTBF_TRAP_CR2 4 + +/* EFLAGS masks. */ +#define CF_MASK 0x00000001 +#define IF_MASK 0x00000200 +#define NT_MASK 0x00004000 + +#define __STR(x) #x +#define STR(x) __STR(x) + +/* AUTO-GENERATE the following two cases (quoted vs. unquoted). */ +#ifndef __ASSEMBLY__ + +#define __SAVE_ALL_PRE \ + "cld;" \ + "pushl %eax;" \ + "pushl %ebp;" \ + "pushl %edi;" \ + "pushl %esi;" \ + "pushl %edx;" \ + "pushl %ecx;" \ + "pushl %ebx;" \ + "movb "STR(XREGS_cs)"(%esp),%al;" \ + "testb $3,%al;" \ + "je 1f;" \ + "movl %ds,"STR(XREGS_ds)"(%esp);" \ + "movl %es,"STR(XREGS_es)"(%esp);" \ + "movl %fs,"STR(XREGS_fs)"(%esp);" \ + "movl %gs,"STR(XREGS_gs)"(%esp);" + +#define SAVE_ALL_NOSEGREGS \ + __SAVE_ALL_PRE \ + "1:" + +#define SET_XEN_SEGMENTS \ + "movl $("STR(__HYPERVISOR_DS)"),%edx;" \ + "movl %edx,%ds;" \ + "movl %edx,%es;" + +#define SAVE_ALL \ + __SAVE_ALL_PRE \ + SET_XEN_SEGMENTS \ + "1:" + +#else + +#define __SAVE_ALL_PRE \ + cld; \ + pushl %eax; \ + pushl %ebp; \ + pushl %edi; \ + pushl %esi; \ + pushl %edx; \ + pushl %ecx; \ + pushl %ebx; \ + movb XREGS_cs(%esp),%dl; \ + testb $3,%dl; \ + je 1f; \ + movl %ds,XREGS_ds(%esp); \ + movl %es,XREGS_es(%esp); \ + movl %fs,XREGS_fs(%esp); \ + movl %gs,XREGS_gs(%esp); + +#define SAVE_ALL_NOSEGREGS \ + __SAVE_ALL_PRE \ + 1: + +#define SET_XEN_SEGMENTS \ + movl $(__HYPERVISOR_DS),%edx; \ + movl %edx,%ds; \ + movl %edx,%es; + +#define SAVE_ALL \ + __SAVE_ALL_PRE \ + SET_XEN_SEGMENTS \ + 1: + +#endif + +#endif /* __ASM_DEFNS_H__ */ diff --git a/xen/include/asm-x86/x86_32/current.h b/xen/include/asm-x86/x86_32/current.h index 7d87b89d72..3450cd02cc 100644 --- a/xen/include/asm-x86/x86_32/current.h +++ b/xen/include/asm-x86/x86_32/current.h @@ -31,11 +31,17 @@ static inline execution_context_t *get_execution_context(void) return execution_context; } +/* + * Get the top-of-stack, as stored in the per-CPU TSS. This is actually + * 20 bytes below the real top of the stack to allow space for: + * domain pointer, DS, ES, FS, GS. + */ static inline unsigned long get_stack_top(void) { unsigned long p; - __asm__ ( "orl %%esp,%0; andl $~3,%0" - : "=r" (p) : "0" (STACK_SIZE-4) ); + __asm__ ( "andl %%esp,%0; addl %2,%0" + : "=r" (p) + : "0" (~(STACK_SIZE-1)), "i" (STACK_SIZE-20) ); return p; } diff --git a/xen/include/asm-x86/x86_32/regs.h b/xen/include/asm-x86/x86_32/regs.h index 18b1fdc66d..9adeb9d420 100644 --- a/xen/include/asm-x86/x86_32/regs.h +++ b/xen/include/asm-x86/x86_32/regs.h @@ -1,47 +1,51 @@ #ifndef _I386_REGS_H #define _I386_REGS_H -struct xen_regs { - long ebx; - long ecx; - long edx; - long esi; - long edi; - long ebp; - long eax; - int xds; - int xes; - int xfs; - int xgs; - long orig_eax; - long eip; - int xcs; - long eflags; - long esp; - int xss; +struct xen_regs +{ + /* All saved activations contain the following fields. */ + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + long orig_eax; + long eip; + int xcs; + long eflags; + + /* Only saved guest activations contain the following fields. */ + long esp; + int xss; + int xes; + int xds; + int xfs; + int xgs; }; enum EFLAGS { - EF_CF = 0x00000001, - EF_PF = 0x00000004, - EF_AF = 0x00000010, - EF_ZF = 0x00000040, - EF_SF = 0x00000080, - EF_TF = 0x00000100, - EF_IE = 0x00000200, - EF_DF = 0x00000400, - EF_OF = 0x00000800, - EF_IOPL = 0x00003000, - EF_IOPL_RING0 = 0x00000000, - EF_IOPL_RING1 = 0x00001000, - EF_IOPL_RING2 = 0x00002000, - EF_NT = 0x00004000, /* nested task */ - EF_RF = 0x00010000, /* resume */ - EF_VM = 0x00020000, /* virtual mode */ - EF_AC = 0x00040000, /* alignment */ - EF_VIF = 0x00080000, /* virtual interrupt */ - EF_VIP = 0x00100000, /* virtual interrupt pending */ - EF_ID = 0x00200000, /* id */ + EF_CF = 0x00000001, + EF_PF = 0x00000004, + EF_AF = 0x00000010, + EF_ZF = 0x00000040, + EF_SF = 0x00000080, + EF_TF = 0x00000100, + EF_IE = 0x00000200, + EF_DF = 0x00000400, + EF_OF = 0x00000800, + EF_IOPL = 0x00003000, + EF_IOPL_RING0 = 0x00000000, + EF_IOPL_RING1 = 0x00001000, + EF_IOPL_RING2 = 0x00002000, + EF_NT = 0x00004000, /* nested task */ + EF_RF = 0x00010000, /* resume */ + EF_VM = 0x00020000, /* virtual mode */ + EF_AC = 0x00040000, /* alignment */ + EF_VIF = 0x00080000, /* virtual interrupt */ + EF_VIP = 0x00100000, /* virtual interrupt pending */ + EF_ID = 0x00200000, /* id */ }; #endif diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 1287cdbe04..dee8b783ef 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -92,16 +92,16 @@ typedef struct unsigned long edi; unsigned long ebp; unsigned long eax; - unsigned long ds; - unsigned long es; - unsigned long fs; - unsigned long gs; unsigned long _unused; unsigned long eip; unsigned long cs; unsigned long eflags; unsigned long esp; unsigned long ss; + unsigned long es; + unsigned long ds; + unsigned long fs; + unsigned long gs; } PACKED execution_context_t; typedef u64 tsc_timestamp_t; /* RDTSC timestamp */ diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index e19141ca02..9339bcc318 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA0019 +#define DOM0_INTERFACE_VERSION 0xAAAA001A /************************************************************************/ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index e44696bdbe..297df0e537 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -75,15 +75,8 @@ struct domain unsigned long event_selector; /* 08: entry CS */ unsigned long event_address; /* 12: entry EIP */ - /* Saved DS,ES,FS,GS immediately before return to guest OS. */ - unsigned long failsafe_selectors[4]; /* 16-32 */ - - /* - * END OF FIRST CACHELINE. Stuff above is touched a lot! - */ - - unsigned long failsafe_selector; /* 32: entry CS */ - unsigned long failsafe_address; /* 36: entry EIP */ + unsigned long failsafe_selector; /* 16: entry CS */ + unsigned long failsafe_address; /* 20: entry EIP */ /* * From here on things can be added and shuffled without special attention -- 2.30.2